#include "deverifysig.h"
#include <string>
#include <vector>
#include <stdio.h>
#include <map>
#if __linux
#include <unistd.h>
#endif

using namespace std;

#define STATIC 0
#if STATIC
map<int, size_t> g_ResultMap;
#endif

class String : public string{
public:
    int hashCode(){
        int h = 1;
        for(auto i = this->begin(); i != this->end(); ++i){
            h = (h << 5) - h +  *i;
        }
        return h;
    }
};


static int hashCode(vector<String> &a) {
    if (a.empty())
        return 0;

    int result = 1;

    for (auto element = a.begin(); element != a.end(); ++element){
        result = (result << 5) - result + (element->empty() ? 0 : element->hashCode());
    }
    return result;
}


int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
{
    BIGNUM *btmp;
    int ret = 0;

    btmp = b == NULL ? BN_new() : b;
    if (btmp == NULL)
        return 0;

    if (!BN_rand(btmp, 159, -1, 0))
        goto error;
    if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
        goto error;

    ret = 1;

 error:

    if (btmp != b)
        BN_free(btmp);

    return ret;
}

int DeverifySig::sign(X509_REQ * r, RSA* rsa)
{
    BIO *bio = NULL;
    BUF_MEM * bufptr = 0;
    String tst;
    int h;
#if 0
    X509 *x = X509_REQ_to_X509(r, 3600, m_pKey);
#else
    X509_NAME *xn;
    X509_CINF *xi = NULL;
    EVP_PKEY *pubkey = NULL;
    X509 *x = X509_new();
    if (x == NULL) {
        return -1;
    }

    ASN1_INTEGER *sno = ASN1_INTEGER_new();
    if (sno == NULL || !rand_serial(NULL, sno))
        goto end;
    if (!X509_set_serialNumber(x, sno))
        goto end;
    ASN1_INTEGER_free(sno);
    sno = NULL;

    xn = X509_REQ_get_subject_name(r);
    if (X509_set_subject_name(x, xn) == 0)
        goto end;
    if (X509_set_issuer_name(x, xn) == 0)
        goto end;
        
    if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL)
        goto end;
    if (X509_gmtime_adj(X509_getm_notAfter(x), (long)60 * 60 * 24 * 7000) == NULL)
        goto end;

    pubkey = X509_REQ_get0_pubkey(r);
    if (pubkey == NULL || !X509_set_pubkey(x, pubkey))
        goto end;

    if (!X509_sign(x, m_pKey, EVP_md5()))
        goto end;
#endif
    bio = BIO_new(BIO_s_mem());
    i2d_X509_bio(bio, x);

    BIO_get_mem_ptr(bio, &bufptr);
    
    tst.assign(bufptr->data, bufptr->length);
    h = 31 + tst.hashCode();

    if(bio){
        BIO_free(bio);
    }

#if STATIC
    {
        auto item = g_ResultMap.find(h);
        if(item == g_ResultMap.end()){
            g_ResultMap[h] = 1;
        }else{
            item->second += 1;
            if(item->second > 10)
                printf("\n%d %d\n", h, item->second);
        }
    }
#endif
    
    //printf("%d\n", h);
    
    if(h == 738285597){
        printf("OK!!!!!!!!!!!!\n");
                /* 提取私钥 */
        FILE *filename = NULL;
        filename = fopen("privateKey.pem", "wb");
        PEM_write_RSAPrivateKey(filename, rsa, NULL, NULL, 0, NULL, NULL);
        fclose(filename);

        bio = BIO_new_file("certificate.pem", "wb");
        PEM_write_bio_X509(bio, x);
        if(bio){
            BIO_free(bio);
        }

        exit(0);
    }
end:
    if(x){
        X509_free(x);
    }
    return 0;
}


std::string hex_to_bytes(std::string hex)
{
    if (hex.size() % 2 != 0)
        hex = std::string("0") + hex;

    std::string result(hex.size() / 2, '\0');
    for (size_t i = 0; i < result.size(); i++) {
        result[i] = (uint8_t)strtol(hex.substr(i * 2, 2).c_str(), NULL, 16);
    }

    return result;
}


void tsthash()
{
#if 1
    String tst;
    tst.assign("3082033130820219a0030201020204010ba281300d06092a864886f70d01010b05003048310a3008060355040613016d310a3008060355040813016d310a3008060355040713016d310a3008060355040a13016d310a3008060355040b13016d310a3008060355040313016d3020170d3138303930353037343932395a180f32303733303630383037343932395a3048310a3008060355040613016d310a3008060355040813016d310a3008060355040713016d310a3008060355040a13016d310a3008060355040b13016d310a3008060355040313016d30820122300d06092a864886f70d01010105000382010f003082010a028201010082261fe2a4b4d97ba4ba9f42fad0cda166b785e1323e4d0dbc1e6fa9a6d46cac0288c3a8688c59356d0228e4e32b7d1ced5ddad270982028ade0d3f5418b0dd601477f4576d559f9ec096a8b26fe72780e2c1137d8248fd9e62c02619b59bc34dc038da7639bcc3d9d1438316b03c1131c15365c98b042d43af7f76aaf97441f3491df09109e09c2948426b6fe604a9698abcc25ece3938017fc8b643705544f502d1626713cdcf86737d52ecf0424a2c42ecd5a4f6cb111f46163e0ce01d2d33f3e64744edf20b8a000cf19761e7c3304d26da713c0626a5d7ec94b033df680f4ddb666823774ff23f58f06bc5b19b591660116a0923e672d2dbd04241db09d0203010001a321301f301d0603551d0e041604147ac843a5f4ca42802e428eacacda7223e84c92a5300d06092a864886f70d01010b050003820101002c45e06132e86ad12ed6447cd4a425c6da8523207bc5ce246d12f9c4cd46f0a6d38e6cd9eb0cd749e5f2ca28f83ce71726e533e04abe470289582cfc888f8a1c8c41793ac76cd261383b890408ffdfc0b2051aec640d6aa2a34cfeb9ddc0166ecb794b5233263c08c7d897ee1c19fed209ac474335aa37742aae2b6cadbe60a93d7e2ed174c783ac920832f7d9f6a1106fbb78237e4a85649aec0760c4bb3e5a3322284346648d8424f89a1286451b0935e8d661de9ded8555270060c4157f3c6ded3cf3ad380e2205ff40a9917d185a680ddb87f31aa25a7473c94b6ffdd2e33e3499b7fd02280c2c153ed367bb861c9259451ba3a6b7ad4adbffadb4c4acac");
    string temp = hex_to_bytes(tst);
    tst.assign(temp);

    vector<String> v;
    v.push_back(tst);
    int h = hashCode(v);
    printf("%d\n", h);
    h = 31 + tst.hashCode();
    //-565395628
    printf("%d\n", h);
#endif
}
